import 'dart:developer';

import 'package:dio/dio.dart';
import 'package:xin_he/service/xin_he_configure.dart';
import 'dart:io';
import 'dart:convert';
import 'package:flutter/foundation.dart';

import 'package:xin_he/utils/xin_he_toast.dart';
import 'xin_he_url_class.dart';
class XinHeRequestDataResult {
  //服务器返回的json数据模型
  dynamic data;

  //此次接口操作是否成功
  bool result;

  //是否网络异常 1网络问题  0 服务器问题
  bool? IOError;

  //紧接着需要调用的方法-一般不需要用到
  Function? next;

  XinHeRequestDataResult(this.data, this.result, {this.next, this.IOError});
}

class XinHeHttpRequestData {
  ///方法名 Unite_Post
  ///
  ///方法介绍 基本请求-通用
  ///
  ///@url - 请求url链接
  ///
  ///@requestData - 请求参数包
  ///
  ///@requestSuccessEvent - 请求成功回调事件
  ///
  ///@requestErrorEvent - 请求失败回调事件
  ///
  ///@timeoutEvent - 请求超时回调事件
  ///
  ///@timeoutTime - 超时时间-默认使用全局
  ///
  ///@isShowLoading - 是否需要显示加载动画
  ///
  ///@isPost - 是否是post请求
  ///
  ///@dismissToast - 是否去掉全局弹窗
  ///
  ///@loadingText - loading文本
  ///
  ///@isLongAwaitShow - 长时间等待是否出现加载弹窗
  ///
  ///@isPrintErrorLog - 是否打印报错msg
  ///
  ///@cancelToken - 请求取消用的token
  ///
  ///@isUnpack - 是否解包，默认只返回data里面的数据
  static Future<XinHeRequestDataResult> requestUniversalPost({
    required String url,
    Map<String, dynamic>? params,
    Object ? bodyData, //使用对象设置data
    Function? requestSuccessEvent,
    Function? requestErrorEvent,
    Function? timeoutEvent,
    Duration? timeoutTime,
    bool isShowLoading = false,
    bool isPost = true,
    bool isLongAwaitShow = true,
    bool isPrintErrorLog = true,
    bool dismissToast = true,
    bool isUnpack = true,
    String? loadingText,
    CancelToken? cancelToken,
    bool isPostAndwwwForm=false,
    bool isPostAndFormData = false,
  }) async {
    //此Api请求是否需要等待弹窗
    if (isShowLoading) {
      //展示加载弹窗
      XinHeToast.xinHeloading(loadingText);
    } else {
      //如果接口不需要加载动画 接口超过1000ms没有返回将会出现加载等待动画
      // isShowLoading = true;
      Future.delayed(const Duration(milliseconds: 1000)).then((value) {
        if (isShowLoading && isLongAwaitShow) {
          //展示弹窗动画
          XinHeToast.xinHeloading(loadingText);
        }
      });
    }
    // //拼接最终请求参数
    Map<String, dynamic> resParams = {
      "isUnpack": isUnpack,
    };
    resParams.addAll(params ?? {});

    //声明请求对象
    Future<Response> response;
    // if (isPost) {
    //   httpRequestManager.dio.options.contentType = 'application/json';
    //   // httpManager.dio.options.responseType = ResponseType.plain;
    //   response = httpRequestManager.dio.post( url,data: resParams, );
    // } else {
    //   // httpRequestManager.dio.options.contentType = 'application/x-www-form-urlencoded';
    //   response = httpRequestManager.dio.get( url, queryParameters: resParams);
    // }
    if (isPost) {
      httpRequestManager.dio.options.contentType = 'application/json';
      // httpManager.dio.options.responseType = ResponseType.plain;
      if(isPostAndwwwForm){
        httpRequestManager.dio.options.contentType = 'application/x-www-form-urlencoded';
      }
      if(isPostAndFormData){
        httpRequestManager.dio.options.contentType = 'multipart/form-data';
      }
      response = httpRequestManager.dio.post(url.contains('http')? url: XinHeHostUrlClass.hostUrl + url,data: resParams, );
    } else {
      // httpRequestManager.dio.options.contentType = 'application/x-www-form-urlencoded';
      response = httpRequestManager.dio.get(url.contains('http')? url: XinHeHostUrlClass.hostUrl + url, queryParameters: resParams);
    }

    //链式结果回调
    return response.then((value) {
      if (requestSuccessEvent != null) {
        requestSuccessEvent(value.data);
      }
      return XinHeRequestDataResult(value.data ?? {}, true);
    }).timeout(
      timeoutTime ?? const Duration(seconds: 20),
      onTimeout: () async {
        if (timeoutEvent != null) timeoutEvent();
        //请求超时输出
        return XinHeRequestDataResult({"message":"请求超时"}, false);
      },
    ).onError((e, stackTrace) {
      String? logInfo;
      bool isIoError = false;
      if (e is DioException) {

        if (e.response?.data != null) {
          //取出errormsg
          if ((e.response!).data is String) {
            logInfo = e.response?.data;
            try{
              Map map = jsonDecode((e.response!).data);
              if (requestErrorEvent != null) requestErrorEvent(map['message'] ?? "服务器开小差了");
              return XinHeRequestDataResult(map, false);
            }catch(e){
              if (requestErrorEvent != null) requestErrorEvent("数据异常");
              return XinHeRequestDataResult({"message":"数据异常"}, false);
            }
          }

          /// 请求后返回服务器返回错误信息
          if ((e.response!).data is Map) {
            logInfo =  json.encode(e.response?.data);
            Map map = (e.response!).data;
            isIoError = false;
            if (requestErrorEvent != null) requestErrorEvent(map['message'] ?? "服务器开小差了");
            return XinHeRequestDataResult((e.response!).data, false);
          }
        }  else if(e.message != null) {
          logInfo = e.message;
        }else {
          /// 大概率 网络关闭异常信息
          if(e.error is SocketException){
            isIoError = true;
            SocketException se = e.error as SocketException;
            logInfo = se.message?? '';
            if (requestErrorEvent != null) {
              requestErrorEvent("网络异常");
            }
            return XinHeRequestDataResult({"message":"网络异常"}, false);
          }
        }

      } else if (e is String) {
        logInfo = e;
      }else {

      }

      log('请求错误=>$url=>$logInfo');
      if (isPrintErrorLog &&
          (e is DioError) &&
          e.response != null &&
          (e.response!).data != null) {
        DioError error = e;
        XinHeToast.center((error.response!).data.toString());
        //取出errormsg
        if ((error.response!).data is String) {
          try{
            Map map = jsonDecode((e.response!).data);
            if (requestErrorEvent != null) requestErrorEvent(map['message'] ?? "服务器开小差了");
            return XinHeRequestDataResult(map, false);
          }catch(e){
            if (requestErrorEvent != null) requestErrorEvent("数据异常");
            return XinHeRequestDataResult({"message":"数据异常"}, false);
          }
        }

        if ((error.response!).data is Map) {
          Map map = (error.response!).data;
          if (requestErrorEvent != null) requestErrorEvent(map['message'] ?? "服务器开小差了");
          return XinHeRequestDataResult((error.response!).data, false);
        }
      }

      if (requestErrorEvent != null) requestErrorEvent(log);
      return XinHeRequestDataResult(e, false,IOError: isIoError);
    }).catchError((e) {
      String? logInfo;
      //区分是否是网络异常
      bool isIoError = false;

      if (e is DioError) {
        logInfo = e.response?.data;
        //取出errormsg
        if ((e.response!).data is String) {
          try{
            Map map = jsonDecode((e.response!).data);
            if (requestErrorEvent != null) requestErrorEvent(map['message'] ?? "服务器开小差了");
            return XinHeRequestDataResult(map, false);
          }catch(e){
            if (requestErrorEvent != null) requestErrorEvent("数据异常");
            return XinHeRequestDataResult({"message":"数据异常"}, false);
          }
        }

        if ((e.response!).data is Map) {
          Map map = (e.response!).data;
          if (requestErrorEvent != null) requestErrorEvent(map['message'] ?? "服务器开小差了");
          return XinHeRequestDataResult((e.response!).data, false);
        }
      } else if (e is String) {
        logInfo = e;
      }
      log('请求异常=>$url=>$logInfo');

      if (isPrintErrorLog &&
          (e is DioError) &&
          e.response != null &&
          (e.response!).data != null) {
        DioError error = e;
        XinHeToast.center((error.response!).data.toString());
        //取出errormsg
        if ((error.response!).data is String) {
          try{
            Map map = jsonDecode((e.response!).data);
            if (requestErrorEvent != null) requestErrorEvent(map['message'] ?? "服务器开小差了");
            return XinHeRequestDataResult(map, false);
          }catch(e){
            if (requestErrorEvent != null) requestErrorEvent("数据异常");
            return XinHeRequestDataResult({"message":"数据异常"}, false);
          }
        }

        if ((error.response!).data is Map) {
          Map map = (error.response!).data;
          if (requestErrorEvent != null) requestErrorEvent(map['message'] ?? "服务器开小差了");
          return XinHeRequestDataResult((error.response!).data, false);
        }

      }
      if (requestErrorEvent != null) requestErrorEvent(log);
      return XinHeRequestDataResult(e, false,IOError: isIoError);


    }).whenComplete(() {
      if (dismissToast) {
        XinHeToast.cancel();
        isShowLoading = false;
      }
    });
  }

  static Future<XinHeRequestDataResult> requestOnlyDataPost({
    required String url,
    Map<String, dynamic>? params,
    Object ? bodyData, //使用对象设置data
    Function? requestSuccessEvent,
    Function? requestErrorEvent,
    Function? timeoutEvent,
    Duration? timeoutTime,
    bool isPost = true,
    bool isPrintErrorLog = true,
    bool dismissToast = true,
    bool isUnpack = true,
    String? loadingText,
    CancelToken? cancelToken,
  }) async {
    // //拼接最终请求参数
    Map<String, dynamic> resParams = {
      "isUnpack": isUnpack,
    };
    resParams.addAll(params ?? {});

    //声明请求对象
    Future<Response> response;
    if (isPost) {
      httpRequestManager.dio.options.contentType = 'application/json';
      // httpManager.dio.options.responseType = ResponseType.plain;
      // if(isPostAndwwwForm){
      //   httpRequestManager.dio.options.contentType = 'application/x-www-form-urlencoded';
      // }
      response = httpRequestManager.dio.post(url.contains(XinHeHostUrlClass.hostUrl)? url: XinHeHostUrlClass.hostUrl + url,data: resParams, );
    } else {
      // httpRequestManager.dio.options.contentType = 'application/x-www-form-urlencoded';
      response = httpRequestManager.dio.get(url.contains(XinHeHostUrlClass.hostUrl)? url: XinHeHostUrlClass.hostUrl + url, queryParameters: resParams);
    }

    //链式结果回调
    return response.then((value) {
      return XinHeRequestDataResult(value.data ?? {}, true);
    }).timeout(
      timeoutTime ?? const Duration(seconds: 15),
      onTimeout: () async {
        if (timeoutEvent != null) timeoutEvent();
        //请求超时输出
        return XinHeRequestDataResult({}, false);
      },
    ).onError((e, stackTrace) {
      return XinHeRequestDataResult({}, false);
    }).catchError((e) {
      return XinHeRequestDataResult({}, false);
    });
  }

  /// 通过隔离线程请求
  Future<XinHeRequestDataResult> requestCompute(
      Future<XinHeRequestDataResult> Function(String) event) async {
    return await compute(event, '');
  }


}
